#include<queue>
#include<iostream>
#include<pthread.h>
#include<unistd.h>
#include<cstdio>
#include<string>
using namespace std;
const int gDefaultCap = 5;

template<class T>
class BlockQueue
{
private:
    bool isQueueFull()
    {
        return bq_.size()==capacity_;
    }
    bool isQueueEmpty()
    {
        return bq_.size()==0;
    }
public:
    BlockQueue(int capacity=gDefaultCap)
        :capacity_(capacity)
    {
        pthread_mutex_init(&mtx_,nullptr);
        pthread_cond_init(&Empty,nullptr);
        pthread_cond_init(&Full,nullptr);

    }
    void push(const T& in)
    {
        pthread_mutex_lock(&mtx_);
        while(isQueueFull()) pthread_cond_wait(&Full, &mtx_);
        bq_.push(in);
        pthread_cond_signal(&Empty);
        pthread_mutex_unlock(&mtx_);

    }
    void pop(T* out)
    {
        pthread_mutex_lock(&mtx_);
        while (isQueueEmpty()) pthread_cond_wait(&Empty, &mtx_);
        *out=bq_.front();
        bq_.pop();
        pthread_cond_signal(&Full);
        pthread_mutex_unlock(&mtx_);
    }
    ~BlockQueue()
    {
        pthread_mutex_destroy(&mtx_);
        pthread_cond_destroy(&Empty);
        pthread_cond_destroy(&Full);
    }
private:
    queue<T> bq_;//阻塞队列
    int capacity_;//容量
    pthread_mutex_t mtx_;
    pthread_cond_t Empty;
    pthread_cond_t Full;
};